package auction;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.rmi.NotBoundException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import util.KeyReader;

import analytics.AnalyticsServer;
import billing.BillingServer;
import billing.BillingServerSecure;

/**
 * Server Main Program
 *
 * @author Gernot Winkler (0929255)
 *
 */
public class Server {
    
    private static int registryPort;
    private static String registryHost;

    /**
     * @param args
     */
    
    public static void main(String[] args) {
        final String AUCTION_SERVER_USER = "auctionserver";
        final String AUCTION_SERVER_PASSWORD = "sadg92tg421";
        
        final String COMMAND_DISCONNECT="!dc";
        final String COMMAND_RECONNECT="!rc";
        final String COMMAND_QUIT = "!exit";
        
        int serverport;
        ServerSocket ss = null;
        AccountManager am;
        
        if (args.length != 5) {
            System.out.println("usage: java auction.Server <Listening Port> <RMI analyticsName> <RMI billingName>");
        } else {
            try {
            	KeyReader kr = KeyReader.getInstance();
            	kr.setPriKeyPath(args[3]);
            	kr.setPubKeyPath(args[4] + "<user>.pub.pem");
            	kr.setSecKeyPath(args[4] + "<user>.key");
            	kr.readPrivateKey(true, "");
            	
                serverport = Integer.parseInt(args[0]);
                
                ss = new ServerSocket(serverport);

                if (!loadProperties()) {
                	ss.close();
                	return;
                }
                Registry registry = LocateRegistry.getRegistry(registryHost, registryPort);
                AnalyticsServer analyticsServer;
                BillingServer billingServer;
                BillingServerSecure billingServerSecure;
                try {
					analyticsServer = (AnalyticsServer) registry.lookup(args[1]);
				} catch (NotBoundException e) {
					System.out.println("Could not find RMI-object AnalyticsServer");
					throw e;
				}
                try {
					billingServer = (BillingServer) registry.lookup(args[2]);
					
				    billingServerSecure=billingServer.login(AUCTION_SERVER_USER,AUCTION_SERVER_PASSWORD);
					
					
				} catch (NotBoundException e) {
					System.out.println("Could not find RMI-object BillingServer");
					throw e;
				}
               
               
                
                //Start Server Listener, constructor starts thread
                am = new AccountManager(analyticsServer, billingServerSecure);
                ConnectionManager cm = new ConnectionManager(ss, am, analyticsServer,billingServerSecure);
                
                
                //Listen to commandline - wait for input, then close
                //System.in.read();      
                System.out.println("Auction Server running. Enter \"!exit\" to exit");
                
                
                
                
                //util.Util.waitForExit();
                boolean running = true;
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                boolean connected = true;
                while (running) {
                    String s = br.readLine();
                    
                    if (s==null){
                        running = false;
                    } else if(s.matches(COMMAND_DISCONNECT)) {
                        if (connected){
                          cm.diconnect();
                          am.stopClientThreads();
                          ss.close();
                          connected = false;
                          System.out.println("Server connection stopped!");
                        } else {
                            System.out.println("Already disconnected!");
                        }
                    } else if(s.matches(COMMAND_RECONNECT)) {
                        if (!connected) {
                            ss = new ServerSocket(serverport);
                            cm = new ConnectionManager(ss, am, analyticsServer,billingServerSecure);
                            connected=true;
                            System.out.println("Server connection working again!");
                        } else {
                            System.out.println("Already connected!");
                        }
                    } else if(s.matches(COMMAND_QUIT)) {
                        running =false;
                    } else {
                        System.out.println("Unknown Command: "+s);
                    }
                    
                }
                
                
                
                
                
                //Shutdown Process
                
                System.out.println("Starting Shutdown...");
                System.out.println("ThreadCount: "+ Thread.activeCount());
                cm.shutdown();
                /*try {
                    cm.join();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }*/
                
                
            } catch (NumberFormatException e){
                System.out.println("Port must be a number!");
            } catch (IOException e) {
                System.out.println("IOException: "+e.getMessage());
            } catch (NotBoundException e) {
            	//nothing
            } finally {
            	try {
            		if (ss != null) {
            			ss.close();
            		}
				} catch (IOException e) {
					System.out.println("Could not close socket");
				}
            }
        }
    }
	
	
	
	private static boolean loadProperties() {
		boolean ok = false;
		java.io.InputStream is = ClassLoader.getSystemResourceAsStream("registry.properties");
		if (is != null) {
			java.util.Properties props = new java.util.Properties();
			try {
				props.load(is);
				registryHost = props.getProperty("registry.host");
				registryPort = Integer.parseInt(props.getProperty("registry.port"));
				ok = true;
			} catch (IOException e) {
				System.err.println("Could not load registry.properties");
			} catch (NumberFormatException e) {
				System.err.println("registry.port in registry.properties must be integer");
			}
			finally {
				try {
					is.close();
				} catch (IOException e) {
					System.err.println("could not close registry.properties");
				}
			}
		} else {
			System.err.println("Properties file not found!");
		}
		return ok;
	}	
}
